package process

import (
    "encoding/json"
    "fmt"
    "gitee.com/HyoJoo-W/ChatRoom/common/message"
    "gitee.com/HyoJoo-W/ChatRoom/server/model"
    "gitee.com/HyoJoo-W/ChatRoom/server/utils"
    "net"
)

type UserProcess struct {
    Conn   net.Conn
    UserId int //表明该连接属于哪个User
}

// ServerProcessLogin 处理登录
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
    //从msg中取出Data并反序列化
    var loginMes message.LoginMes
    err = json.Unmarshal([]byte(mes.Data), &loginMes)
    if err != nil {
        fmt.Println("loginMes反序列化失败 err = ", err)
        return
    }
    //1 提前声明服务器端返回消息
    var resMes message.Message
    resMes.Type = message.LoginResMesType

    //2 声明返回消息的数据部分
    var loginResMes message.LoginResMes

    //3 验证客户端提交的登录请求
    user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
    if err != nil {
        if err == model.ErrorUserNotExists {
            loginResMes.Code = 500
            loginResMes.Error = err.Error()
        } else if err == model.ErrorUserPwd {
            loginResMes.Code = 403
            loginResMes.Error = err.Error()
        } else {
            loginResMes.Code = 505
            loginResMes.Error = "服务器内部错误"
        }
    } else {
        loginResMes.Code = 200
        //将登录后的User存入在线用户表
        this.UserId = loginMes.UserId
        userMgr.AddOnlineUser(this)                  //将自己添加到在线用户表中
        this.NotifyOtherOnlineUsers(loginMes.UserId) //通知其他在线用户我上线了

        //将当前在线用户ids放入loginResMes.UserIds
        for id, _ := range userMgr.onlineUsers {
            loginResMes.UserIds = append(loginResMes.UserIds, id)
        }

        fmt.Println(user, "登录成功")
    }

    //4 将loginMes序列化放入返回消息中
    data, err := json.Marshal(loginResMes)
    if err != nil {
        fmt.Println("loginMes序列化失败 err = ", err)
        return
    }
    resMes.Data = string(data)

    //5 序列化resMes,发送给客户端
    data, err = json.Marshal(resMes)
    if err != nil {
        fmt.Println("resMes序列化失败 err = ", err)
        return
    }

    //创建一个Transfer实例
    tf := &utils.Transfer{
        Conn: this.Conn,
    }
    err = tf.WritePkg(data)
    return
}

// ServerProcessRegister 服务器端处理注册请求
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
    //从msg中取出Data并反序列化
    var registerMes message.RegisterMes
    err = json.Unmarshal([]byte(mes.Data), &registerMes)
    if err != nil {
        fmt.Println("registerMes反序列化失败 err = ", err)
        return
    }

    //1 提前声明服务器端返回消息
    var resMes message.Message
    resMes.Type = message.RegisterResMesType

    //2 声明返回消息的数据部分
    var registerResMes message.RegisterResMes

    //3 验证客户端提交的登录请求
    err = model.MyUserDao.Register(&registerMes.User)
    if err != nil {
        if err == model.ErrorUserExists {
            registerResMes.Code = 505
            registerResMes.Error = model.ErrorUserExists.Error()
        } else {
            registerResMes.Code = 506
            registerResMes.Error = "[注册]未知错误"
        }
    } else {
        registerResMes.Code = 200
    }

    //4 将registerResMes序列化放入返回消息中
    data, err := json.Marshal(registerResMes)
    if err != nil {
        fmt.Println("[注册]registerResMes序列化失败 err = ", err)
        return
    }
    resMes.Data = string(data)

    //5 序列化resMes,发送给客户端
    data, err = json.Marshal(resMes)
    if err != nil {
        fmt.Println("[注册]resMes序列化失败 err = ", err)
        return
    }

    //创建一个Transfer实例
    tf := &utils.Transfer{
        Conn: this.Conn,
    }
    err = tf.WritePkg(data)
    return
}

// NotifyOtherOnlineUsers 服务器将新上线用户的消息推送给其他在线用户
func (this *UserProcess) NotifyOtherOnlineUsers(userId int) {
    for id, up := range userMgr.onlineUsers {
        //过滤自己
        if userId == id {
            continue
        }
        up.NotifyOthers(userId)
    }
}

// NotifyOthers 通知其他在线用户某一用户上线了
func (this *UserProcess) NotifyOthers(userId int) {
    var mes message.Message
    mes.Type = message.NotifyUserStatusMesType

    var notifyUserStatusMes message.NotifyUserStatusMes
    notifyUserStatusMes.UserId = userId
    notifyUserStatusMes.Status = message.UserOnline

    //序列化
    data, err := json.Marshal(notifyUserStatusMes)
    if err != nil {
        fmt.Println("序列化失败, err = ", err)
        return
    }
    mes.Data = string(data)

    //序列化mes,发送
    data, err = json.Marshal(mes)
    if err != nil {
        fmt.Println("序列化失败, err = ", err)
        return
    }
    tf := &utils.Transfer{
        Conn: this.Conn,
    }
    err = tf.WritePkg(data)
    if err != nil {
        fmt.Println("推送新登录用户状态失败,err = ", err)
        return
    }

}
